﻿// 903 字典序最小欧拉路.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <memory.h>
#include <algorithm>


using namespace std;
/*
http://oj.daimayuan.top/course/14/problem/764
给你一张无向图，你需要求出这张图中字典序最小的欧拉回路（数据保证一定存在）。

图用以下形式给出：

第一行输入两个整数 n,m
，表示图的顶点数和边数，顶点编号从 1
 到 n
。

接下来 m
 行，每行两个整数 x,y
，表示 x
 和 y
 之间有一条边。

输出一行 m+1
 个数表示欧拉回路依次经过的顶点，用空格隔开，第一个数和最后一个数应该相同。

输入格式
第一行两个整数 n,m
。

接下来 m
 行，每行有两个整数，代表一条边。

输出格式
输出一行 m+1
 个数。

样例输入
5 6
1 2
1 3
2 3
2 4
2 5
4 5
样例输出
1 2 4 5 2 3 1
数据规模
对于所有数据，保证 2≤n≤1000,0≤m≤10000,1≤x,y≤n
。
*/
struct Node {
	int y, idx;
	Node(int _y, int _idx) { y = _y; idx = _idx; }
	bool operator < (const Node &A)const {
		return y < A.y;
	}
};
vector<Node>  edge[100010];
int n, m, cnt = 1, l, f[100010], v[100010], c[100010], d[100010];
bool b[200010];

void dfs(int x) {
	while (f[x] < v[x]) {
		int y = edge[x][f[x]].y, idx = edge[x][f[x]].idx;
		if (!b[idx]) {
			++f[x];
			b[idx] = b[idx ^ 1] = true;
			dfs(y);
			c[++l] = y;
		}
		else {
			++f[x];
		}
	}
}

void Euler() {
	int x = 0;
	for (int i = 1; i <= n; i++) {
		if (d[i]) {
			x = i; break;
		}
	}

	memset(b, false, sizeof b);
	memset(f, 0, sizeof f);
	l = 0;
	dfs(x);
	c[++l] = x;

	for (int i = l; i; --i) {
		printf("%d ",c[i]);
	}
	
}



int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d%d", &x, &y);
		edge[x].push_back(Node(y, ++cnt));
		edge[y].push_back(Node(x, ++cnt));
		++d[x]; ++d[y];
	}
	for (int i = 1; i <= n; i++) {
		v[i] = edge[i].size();
		sort(edge[i].begin(),edge[i].end());
	}
	Euler();

	return 0;
}
